const http = require('http')

const handler = Symbol('handler')
const createContext = Symbol('createContext')
const handleRequest = Symbol('handleRequest')
const middlewareList = Symbol('middlewareList')

// 组合中间件
function compose(middlewareList) {
	return function (ctx) {
		// 中间件调用
		function dispatch(i) {
			const middleware = middlewareList[i]
			try {
				return Promise.resolve(middleware(ctx, dispatch.bind(null, i + 1)))
			} catch (err) {
				return Promise.reject(err)
			}
		}

		return dispatch(0)
	}
}

class LikeKoa2 {
	constructor() {
		this[middlewareList] = []
	}

	use(middleware) {
		this[middlewareList].push(middleware)
		return this
	}

	[createContext](req, res) {
		const ctx = { req, res }
		ctx.query = req.query
		return ctx
	}

	[handleRequest](ctx, middleware) {
		return middleware(ctx)
	}

	[handler] = (req, res) => {
		const middleware = compose(this[middlewareList])
		const ctx = this[createContext](req, res)
		return this[handleRequest](ctx, middleware)
	}

	listen(...args) {
		const server = http.createServer(this[handler])
		server.listen(...args)
	}
}

module.exports = LikeKoa2
